home *** CD-ROM | disk | FTP | other *** search
- /**********************************************************************
- *
- * *** HAPPy Pascal compiler ***
- * 各種サブルーチン群
- *
- * void skip(Set fsys)
- * void updatelc(int upsize)
- * void getbounds(stp *fsp,long *fmin, long *fmax)
- * boolean equalbounds(stp *fsp1, stp *fsp2)
- * int align(stp *fsp,int flc)
- * void conststrings(stp **fsp, union valu *fvalu)
- * void constant(Set fsys, stp **fsp, union valu *fvalu)
- * boolean compatible(stp *fsp1,stp *fsp2)
- * boolean assigncompati(stp *fsp1,stp *fsp2)
- * boolean string(stp *fsp)
- *
- * Copyright (c) H.Asano 1992,1994.
- *
- **********************************************************************/
-
- #define EXTERN extern
- #include <string.h>
- #include "pascomp.h"
-
- typedef enum _sign {none, pos, neg } signflag ;
-
- boolean string(stp*) ;
- extern void pcerr(int,char*) ;
- extern void insymbol(void) ;
- extern ctp *searchid(Set) ;
- extern Set *mkset(Set*,int,...) ;
- extern Set *orset(Set*,Set*) ;
- extern void term(void) ;
- extern void *Malloc(int) ;
- extern void applied(ctp*,int) ;
-
- /**************************************/
- /* skip() : 誤り回復のためにsymbolを */
- /* キーにして読み飛ばす */
- /**************************************/
- void skip(Set fsys)
- {
- while(! inset(fsys,sy))
- insymbol() ;
- }
-
- /**************************************/
- /* updatelc() : location counter更新 */
- /**************************************/
- void updatelc(int upsize)
- {
- if(Maxaddr-upsize < lc)
- pcerr(609,"") ; /* 変数割当できない */
- else lc += upsize ; /* lc を更新 */
- }
-
- /*******************************************************/
- /* getbounds() : 範囲型,文字型,整数型、集合型,列挙型の */
- /* 下限、上限値を求める */
- /* (* assume fsp<>intptr and fsp<>realptr *) */
- /*******************************************************/
- void getbounds(stp *fsp,long *fmin, long *fmax)
- {
- if(!fsp) return ;
-
- if(fsp == charptr) { /* 文字型 */
- *fmin = ordminchar ; /* 一番小さい文字コード */
- *fmax = ordmaxchar ; /* 一番大きい文字コード */
- }
- else if(fsp == intptr) { /* 整数型 */
- *fmin = -Maxint ; /* -Maxint .. Maxint */
- *fmax = Maxint ;
- }
- else if(fsp->form == subrange) { /* 範囲型 */
- *fmin = fsp->sf.su.min ; /* 下限 */
- *fmax = fsp->sf.su.max ; /* 上限 */
- }
- else if(fsp->form == power) { /* 集合型 */
- *fmin = fsp->sf.pw.elmin ; /* 下限 */
- *fmax = fsp->sf.pw.elmax ; /* 上限 */
- }
- else if(fsp->sf.sc.fconst) { /* 列挙型の時 */
- *fmax = fsp->sf.sc.fconst->n.values.ival ; /* 最後の列挙名の値 */
- *fmin = 0 ;
- }
- }
-
- /****************************************/
- /* equalbounds() : 2つの型の上限、下限が */
- /* 等しいか判定する */
- /****************************************/
- boolean equalbounds(stp *fsp1, stp *fsp2)
- {
- long lmin1,lmin2,lmax1,lmax2 ;
-
- if((!fsp1) || (!fsp2)) return(true) ; /* 今のところ意味不明 */
-
- getbounds(fsp1,&lmin1,&lmax1) ; /* fsp1 の下限、上限を調べる */
- getbounds(fsp2,&lmin2,&lmax2) ; /* fsp2 の下限、上限を調べる */
- return((lmin1==lmin2) && (lmax1==lmax2)) ;/* 両方とも等しいとき真*/
- }
-
- /**************************************/
- /* alignquot() : 型の境界を求める */
- /* align の 内部関数 */
- /**************************************/
- static int alignquot(stp *fsp)
- {
- if(!fsp) return(1) ; /* 型ポインタがない時は1 */
-
- switch(fsp->form) {
- case scalar : /* スカラー型 */
- if(fsp==intptr) return(intal) ; /* integer型 */
- if(fsp==boolptr) return(boolal) ; /* boolean型 */
- if(fsp==charptr) return(charal) ; /* char 型 */
- if(fsp==realptr) return(realal) ; /* real 型 */
- if(fsp->sf.sc.scalkind == declared) /* 列挙 型 */
- return(intal) ;
- return(parmal) ; /* parameter list*/
- case subrange : /* 範囲型 */
- return(alignquot(fsp->sf.su.rangetype)) ; /* 範囲の元の型 */
- case pointer : /* ポインタ型 */
- return(adral) ;
- case power : /* 集合型 */
- return(setal) ;
- case files : /* ファイル型 */
- return(fileal) ;
- case arrays : /* 配列型 */
- return(alignquot(fsp->sf.ar.aeltype)) ;
- /* 要素の型 */
- case records : /* レコード */
- return(recal) ;
- /* case variant : */ /* 可変レコード */
- /* case tagfld : */ /* 可変レコードのタグ名 */
- /* このルートはない */
- }
- }
-
- /************************************************/
- /* align() : 型に応じた割りつけ開始番地を求める */
- /* flc : 今の番地 */
- /* return : 割りつけ開始番地 */
- /************************************************/
- int align(stp *fsp,int flc)
- {
- int k, l;
-
- k = alignquot(fsp) ; /* その型の境界値を求める */
- l = flc - 1 + k ; /* flc以上の最小のkの公倍数を */
- return(l - l%k) ; /* 返却する */
- }
-
- /***************************************/
- /* constident(): 名前定数の処理 */
- /***************************************/
- static void constident(signflag fsign,stp **fsp, union valu *fvalu)
- {
- stp *lsp ;
- ctp *lcp ;
- csp *lvp ;
- Set ws ;
-
- mkset(&ws, konst, -1) ;
- lcp = searchid(ws) ; /* 定数の名前から探す */
- applied(lcp,level) ; /* 参照名チェーン */
- lsp = lcp->idtype ;
- *fvalu = lcp->n.values ; /* 名前の値 */
- if(fsign != none) { /* 符号がある時 */
- if(lsp == intptr) { /* 整数 */
- if(fsign == neg)
- (*fvalu).ival = -(*fvalu).ival; /* 値を反転 */
- }
- else if(lsp == realptr) { /* 実数 */
- if(fsign == neg) {
- lvp = (csp*)Malloc(sizeof(csp));
- lvp->cclass = real ;
- lvp->c.rval = (char*)Malloc(Maxdiglng+1+1);
- *(lvp->c.rval) = ((*(*fvalu).valp->c.rval)=='-')/* - * - = + */
- ? (char)' ' : (char)'-' ; /* + * - = - */
- strcpy(lvp->c.rval+1,
- (*fvalu).valp->c.rval+1); /* 中身を移しかえ */
- (*fvalu).valp = lvp ;
- }
- }
- else pcerr(105,lcp->name) ; /* 整数や実数でないのに */
- /* 符号があるので、符号は駄目*/
- /* のエラーメッセージ */
- }
- *fsp = lsp ;
- insymbol() ;
- }
-
- /***************************************/
- /* conststrings(): 文字列定数の処理 */
- /***************************************/
- void conststrings(stp **fsp, union valu *fvalu)
- {
- stp *lsp,*lsp1 ;
-
- if(lgth == 1) lsp = charptr ; /* 1文字は文字型 */
- else if(lgth == 0) lsp = nil ; /* 0文字はエラー */
- else {
- lsp = (stp*)Malloc(sizeof(stp));
- lsp->size = lgth*charsize ; /* 文字列長 */
- lsp->form = arrays ; /* 配列型 */
- lsp->sf.ar.packed = true ; /* 詰め込み型である */
- lsp->sf.ar.aeltype = charptr ; /* 要素の型は文字型 */
- lsp1 = (stp*)Malloc(sizeof(stp)) ;/* 添字の型は */
- lsp1->form = subrange ; /* 範囲型 */
- lsp1->size = intsize ;
- lsp1->sf.su.rangetype = intptr ;
- lsp1->sf.su.min = 1 ; /* 添字の下限値は1 */
- lsp1->sf.su.max = (long)lgth ; /* 添字の上限値は文字列長 */
- lsp->sf.ar.inxtype = lsp1 ; /* 添字の型をこの範囲型とする*/
- }
- *fvalu = val ; /* 文字列を返却 */
- *fsp = lsp ;
- }
-
- /*********************************************/
- /* constant() : 定数の処理 */
- /*********************************************/
- void constant(Set fsys, stp **fsp, union valu *fvalu)
- {
- stp *lsp ;
- signflag sign ;
- Set ws ;
-
- lsp = nil ;
- (*fvalu).ival = 0 ;
-
- if(! inset(constbegsys,sy)) { /* 定数として許されない時 */
- pcerr(50,"") ; /* 定数に誤りがある */
- ws = fsys ;
- orset(&ws,&constbegsys) ;
- skip(ws) ; /* fsys+constbegsysまでskip*/
- }
-
- if(inset(constbegsys,sy)) { /* 定数としてOKの時 */
- if(sy == stringconst) { /* 文字列定数の時 */
- conststrings(fsp,fvalu) ; /* 文字列定数の処理 */
- insymbol() ;
- }
- else {
- /*** 文字列以外の時は まず符号(+ -)の処理をする ***/
-
- sign = none ;
- if((op == plus) || (op == minus)) { /* + - の 時 */
- sign = (op == plus) ? pos : neg ; /* 符号の選別 */
- insymbol() ;
- }
-
- if(sy == ident) /* 名前の時 */
- constident(sign,fsp,fvalu) ; /* 名前定数の処理 */
-
- else if(sy == intconst) { /* 整数定数の時 */
-
- if(sign == neg) val.ival = -val.ival ; /* -の時は値を反転 */
- *fsp = intptr ;
- *fvalu = val ;
- insymbol() ;
- }
-
- else if(sy == realconst) { /* 実数定数の時 */
- if(sign == neg)
- *(val.valp->c.rval) = '-' ; /* 頭に負の符号をつける */
- *fsp = realptr ;
- *fvalu = val ;
- insymbol() ;
- }
-
- else { /* それ以外 */
- pcerr(106,"") ; /* 数がない */
- skip(fsys) ;
- }
- }
- }
-
- if(! inset(fsys,sy)) {
- pcerr(6,"") ; /* 不当な記号が現れた */
- skip(fsys) ;
- }
- }
-
- /********************************************/
- /* compatible() : 2つの型が適合するか判定 */
- /********************************************/
- boolean compatible(stp *fsp1,stp *fsp2)
- {
-
- if(fsp1 == fsp2) return(true) ; /* 型のアドレスが同じなら等しい*/
-
- if((!fsp1) || (!fsp2)) return(true);
- /* どちらかがnilならば、すでに
- エラーメッセージが出ている
- はずなので、ここでさらに
- エラーを検出させないためtrue*/
-
- if(fsp1->form == fsp2->form) /* 型が等しい */
- switch(fsp1->form) {
- case subrange : return /* 部分範囲型 */
- (fsp1->sf.su.rangetype == fsp2->sf.su.rangetype);
- /* 両方が 同じ型 */
-
- case power : /* 集合型 */
- if((fsp1->sf.pw.packed == both) ||
- (fsp2->sf.pw.packed == both))
- return(compatible(fsp1->sf.pw.elset, /*基底の型*/
- fsp2->sf.pw.elset )) ;/*のD適合*/
- else return
- (!(fsp1->sf.pw.packed ^ fsp2->sf.pw.packed) &&
- /* 両方とも詰めなしか詰めあり */
- compatible(fsp1->sf.pw.elset, /* 基底の型が*/
- fsp2->sf.pw.elset )) ; /* 適合 */
-
- case pointer : return /* ポインタ型 */
- ((fsp1 == nilptr) || (fsp2 == nilptr)) ;
- /* nilは全てのポインタ型と適合 */
-
- case arrays : return /* 配列型 */
- (string(fsp1) && string(fsp2) &&
- (fsp1->sf.ar.inxtype->sf.su.max ==
- fsp2->sf.ar.inxtype->sf.su.max));
- /* 同数の成分を持つ文字列型の
- 時は適合する */
-
- default : return(false) ; /* それ以外の型は不適合 */
- }
-
- else if(fsp1->form == subrange) /* fsp1がfsp2の部分範囲か */
- return (fsp1->sf.su.rangetype == fsp2) ;
- else if(fsp2->form == subrange) /* fsp2がfsp1の部分範囲か */
- return (fsp1 == fsp2->sf.su.rangetype) ;
- else return(false) ;
- }
-
- /***************************************************/
- /* assigncompati() : 2つの型の代入可能性を判定する */
- /* 型fsp1に対して型fsp2が代入可能の時真 */
- /***************************************************/
- boolean assigncompati(stp *fsp1,stp *fsp2)
- {
- if(fsp1 == fsp2) /* 同じ型 */
- return(fsp1->assignflag) ; /* 代入可能性のチェック */
- else if((fsp1 == realptr) && compatible(fsp2,intptr)) return(true) ;
- else return(compatible(fsp1,fsp2)) ;
- }
-
- /**************************************/
- /* string() : 型が文字列か判定する */
- /**************************************/
- boolean string(stp *fsp)
- {
- if(!fsp) return(false) ;
-
- return
- ((fsp->form == arrays) /* 配列型 */
- && (fsp->sf.ar.packed) /* packed指定あり */
- && (compatible(fsp->sf.ar.aeltype,charptr)) /* 要素の型が文字型*/
- && (fsp->sf.ar.inxtype->form == subrange) /* 添字の型は範囲 */
- && (fsp->sf.ar.inxtype->sf.su.min == 1) /* 下限値は1 */
- && (fsp->sf.ar.inxtype->sf.su.max > 1 )) ; /* 上限値は2以上 */
- /* その時 文字列と認められる */
- /* 上記以外は文字列ではない */
- }